package com.fs.gateway.route;

import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.fs.common.utils.CollUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

@Slf4j
@Component
@RequiredArgsConstructor
public class DynamicRouteLoader {
    private final RouteDefinitionWriter writer;
    private final NacosConfigManager nacosConfigManager;
    private final String dateId = "gateway-routes.json";
    private final String group = "DEFAULT_GROUP";
    private final Set<String> routeIds = new HashSet<>();

    @PostConstruct
    public void initRouteConfigListener() throws NacosException {
        log.info("开始初始化路由配置监听, dataId: {}, group: {}", dateId, group);
        String configInfo = nacosConfigManager.getConfigService()
                .getConfig(dateId, group, 5000);
        log.info("首次拉取配置: {}", configInfo);
        updateConfigInfo(configInfo);

        nacosConfigManager.getConfigService().addListener(dateId, group, new Listener() {
            @Override
            public Executor getExecutor() {
                return null;
            }
            @Override
            public void receiveConfigInfo(String configInfo) {
                log.info("监听到配置变更: {}", configInfo);
                updateConfigInfo(configInfo);
            }
        });
        log.info("路由配置监听器注册成功");
    }

    private void updateConfigInfo(String configInfo) {
        if (configInfo == null || configInfo.trim().isEmpty()) {
            log.warn("路由配置为空，跳过更新");
            return;
        }
        try {
            List<RouteDefinition> routeDefinitions = JSONUtil.toList(configInfo, RouteDefinition.class);
            log.info("解析到 {} 条路由定义", routeDefinitions.size());

            List<Mono<Void>> deleteMonos = routeIds.stream()
                    .map(routeId -> writer.delete(Mono.just(routeId)))
                    .collect(Collectors.toList());
            Mono.when(deleteMonos)
                    .doOnSuccess(v -> routeIds.clear())
                    .then(Mono.fromRunnable(() -> {
                        if (CollUtils.isEmpty(routeDefinitions)) {
                            return;
                        }
                        routeDefinitions.forEach(routeDefinition -> {
                            writer.save(Mono.just(routeDefinition))
                                    .doOnSuccess(v -> log.info("成功保存路由: {}", routeDefinition.getId()))
                                    .doOnError(e -> log.error("保存路由失败: {}", routeDefinition.getId(), e))
                                    .subscribe();
                            routeIds.add(routeDefinition.getId());
                        });
                    }))
                    .subscribe();
        } catch (Exception e) {
            log.error("路由更新失败", e);
        }
    }
}
